#include "stdafx.h"
#include <time.h>
#include "Game.h"
#include "Marco.h"
#include "MenuState.h"
#include "Globals.h"
#include "LookAtCamera.h"
#include "Camera.h"
#include "SoundManager.h"
#include "TextRenderer.h"


Game* Game::instance = NULL;
int countFPS = 0;
int totalFPS = 0;
double currentHour = 0.0;
double currentMin = 0.0;
double currentSec = 0.0;
char oldFPS[100];


Game::Game()
{
	isActive = true;
	isPause = false;
}

Game::Game(ESContext* vesContext)
{
	isActive = true;
	isPause = false;
	this->esContext = vesContext;
	this->stateManager = StateManager::GetInstance();
}


Game::~Game()
{
	Delete(stateManager);
	ResourceManager* resourceManager = ResourceManager::GetInstance();
	Delete(resourceManager);
	SoundManager* snd = SoundManager::getInstance();
	Delete(snd);
	TextRenderer * txt = TextRenderer::GetInstance();
	Delete(txt);
}


Game* Game::GetInstance(ESContext* esContext)
{
	if (!instance)
		instance = new Game(esContext);
	return instance;
}

void Game::Key(ESContext *esContext, unsigned char key, bool bIsPressed)
{
	if (!bIsPressed)
		return;
	switch (key){
	/*case 'W':
		Globals::currentCamera->MoveForward(10.0f);
		break;*/
	/*case 'S':
		Globals::currentCamera->MoveBackward(10.0f);
		break;
	case 'A':
		Globals::currentCamera->MoveLeft(10.0f);
		break;
	case 'D':
		Globals::currentCamera->MoveRight(10.0f);
		break;
	case 'P':
		instance->Pause();
		break;
	case 'R':
		instance->Resume();
		break;
	case 38:
		Globals::currentCamera->RotateUp(3.14f / 90);
		break;
	case 40:
		Globals::currentCamera->RotateDown(3.14f / 90);
		break;
	case 39:
		Globals::currentCamera->RotateRight(0.05f);
		break;*/
	/*case 37:
		Globals::currentCamera->RotateLeft(0.05f);
		break;*/
	case 49:
	{
			   delete Globals::currentCamera;
			   Globals::currentCamera = new LookAtCamera();
			   Globals::currentCamera->projection.SetPerspective(45.0f, 4.0f / 3, 1.0f, 10000.0f);
			   Globals::currentCamera->SetPosition(Vector3(0, 0, 10));
			   LookAtCamera* temp = dynamic_cast<LookAtCamera*>(Globals::currentCamera);
			   /*temp->SetTarget(Vector3(0.0f,0.0f,1.0f));*/
	}
		break;
	case 50:

	{
			   delete Globals::currentCamera;
			   Globals::currentCamera = NULL;
			   Globals::currentCamera = new Camera();
			   if (Globals::currentCamera == NULL)
			   {
				   Globals::currentCamera = new Camera();
			   }
			   Globals::currentCamera->projection.SetPerspective(45.0f, 4.0f / 3, 1.0f, 10000.0f);
			   Globals::currentCamera->SetPosition(Vector3(0, 0, 20.0f));

	}
		break;
	}
	if (instance->stateManager->currentState != NULL)
	{
		if (instance->isActive)
		{
			instance->stateManager->currentState->Key(esContext, key, bIsPressed);
		}
	}
}

void Game::Mouse(ESContext* esContext, MouseData mouseData, bool bIsdown)
{
	if (instance->stateManager->currentState != NULL)
	{
		if (instance->isActive)
		{
			instance->stateManager->currentState->Mouse(esContext, mouseData, bIsdown);
		}
	}
	if (mouseData.type == MouseType::Left)
	{
		Vector2 position = mouseData.position;
		if (bIsdown)
		{
			/*wchar_t* p = (wchar_t*)"Mouse Click";
			MessageBox(esContext->hWnd, p,p, 0);*/
		}
	}
}


//void Game::FakeRun(ESContext* esContext)
//{
//	Run(esContext,0.0f);
//}

void Game::Run(ESContext *esContext, float deltatime)
{
	double tstart, tstop, ttime, trealTime;
	tstart = (double)clock();
	glClear(GL_COLOR_BUFFER_BIT);
	if (instance->stateManager->currentState != NULL)
	{
		if (instance->isActive)
			instance->stateManager->currentState->Update(esContext, deltatime);
		instance->stateManager->currentState->Draw(esContext);
	}
	tstop = (double)clock();
	ttime = (tstop - tstart)/CLOCKS_PER_SEC;
	/*cout << ttime << endl;*/
	/*char text[100];
	DoubleToChar(ttime, 5, text);
	float sx = 2.0f / Globals::screenWidth;
	float sy = 2.0f / Globals::screenHeight;
	TextRenderer::GetInstance()->RenderText(esContext, text, -1 + 8 * sx, 1 - 50 * sy, sx, sy);*/
	//Delete(text);
	if (ttime<1 / Max_FPS)
	{
		double sec = 1 / Max_FPS - ttime;
		Sleep((DWORD)sec * 1000);
	}
	trealTime = (double)clock();
	ttime = (trealTime - tstart)/CLOCKS_PER_SEC;
	/*cout << ttime << endl;*/
	char text[100];
	DoubleToChar(ttime, 5, text);
	float sx = 2.0f / Globals::screenWidth;
	float sy = 2.0f / Globals::screenHeight;
	TextRenderer::GetInstance()->RenderText(esContext, text, -1 + 8 * sx, 1 - 50 * sy, sx, sy);

	countFPS++;
	totalFPS++;
	time_t t = time(0);   // get time now
	struct tm * now = localtime(&t);
	if (oldFPS != 0)
		TextRenderer::GetInstance()->RenderText(esContext, oldFPS, -1 + 8 * sx, 1 - 90 * sy, sx, sy);

	double value = (now->tm_hour - currentHour) * 3600 + (now->tm_min - currentMin) * 60 + (now->tm_sec - currentSec);
	if (value >= 1.0)
	{
		char fps[100];
		_itoa_s(countFPS, fps, 10);
		char fp[100] = "FPS :";
		strcat(fp, fps);
		//TextRenderer::GetInstance()->RenderText(esContext, fp, -1 + 8 * sx, 1 - 90 * sy, sx, sy);
		strcpy_s(oldFPS, fp);
		countFPS = 0;
		currentHour = now->tm_hour;
		currentMin = now->tm_min;
		currentSec = now->tm_sec;
	}

	eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}

void Exit(ESContext* esContext)
{
	StateManager*state = StateManager::GetInstance();
	ResourceManager*resource = ResourceManager::GetInstance();
	SoundManager* snd = SoundManager::getInstance();
	Game* instance = Game::GetInstance(esContext);
	Delete(state);
	Delete(resource);
	Delete(snd);
	delete Globals::currentCamera;
	exit(0);
}


//0: not successs
//1: success load resource
int Game::CreateGame()
{
	
	/*__thiscall _cdecl;*/
	ResourceManager* resourceManager = ResourceManager::GetInstance();
	esInitContext(esContext);
	esCreateWindow(esContext, "New Game", Globals::screenWidth, Globals::screenHeight, ES_WINDOW_RGB | ES_WINDOW_DEPTH);
	if (resourceManager->Load(esContext) != 0)
		return 0;
	SoundManager* snd = SoundManager::getInstance();
	if (snd->Load() == -1)
		return 0;
	float aspect = (GLfloat)esContext->width / (GLfloat)esContext->height;
	Globals::currentCamera->projection.SetPerspective(45.0f, aspect, 1.0f, 10000.0f);
	Globals::currentCamera->SetPosition(Vector3(0.0f, 0.0f, 20.0f));
	return 1;
	//Exit(esContext);
}


void Game::StartGame()
{
	esRegisterUpdateFunc(esContext, Run);
	//esRegisterDrawFunc(esContext, FakeRun);
	esRegisterMouseFunc(esContext, Mouse);
	esRegisterKeyFunc(esContext, Key);


	time_t t = time(0);   // get time now
	struct tm * timeEsp = localtime(&t);
	currentHour = timeEsp->tm_hour;
	currentMin = timeEsp->tm_min;
	currentSec = timeEsp->tm_sec;
	memset(oldFPS, 0, 100);

	esMainLoop(esContext);
}


void Game::Pause()
{
	isActive = false;
}

void Game::Resume()
{
	isActive = true;
}

void Game::AddState(State* newState)
{
	stateManager->AddState(newState);
}